//package com.atguigu.encryption.utils;
//
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
//
//import javax.crypto.Cipher;
//import java.security.*;
//import java.security.spec.InvalidKeySpecException;
//import java.security.spec.PKCS8EncodedKeySpec;
//import java.security.spec.X509EncodedKeySpec;
//import java.util.Base64;
//
//public class SM2Util {
//
//    static {
//        Security.addProvider(new BouncyCastleProvider());
//    }
//    public static String encrypt(String plaintext, String publicKey) throws Exception {
//        Security.addProvider(new BouncyCastleProvider());
//        Cipher cipher = Cipher.getInstance("SM2", "BC");
//        cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
//        byte[] ciphertextBytes = cipher.doFinal(plaintext.getBytes());
//        return Base64.getEncoder().encodeToString(ciphertextBytes);
//    }
//
//    public static String decrypt(String ciphertext, String privateKey) throws Exception {
//        Security.addProvider(new BouncyCastleProvider());
//        Cipher cipher = Cipher.getInstance("SM2", "BC");
//        cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
//        byte[] plaintextBytes = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
//        return new String(plaintextBytes);
//    }
//
//    private static PublicKey getPublicKey(String publicKeyString) throws Exception {
//        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
//        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance("SM2", "BC");
//        return keyFactory.generatePublic(keySpec);
//    }
//
//    private static PrivateKey getPrivateKey(String privateKeyString) throws Exception {
//        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
//        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
//        KeyFactory keyFactory = KeyFactory.getInstance("SM2", "BC");
//        return keyFactory.generatePrivate(keySpec);
//    }
//}


//import lombok.extern.slf4j.Slf4j;
//import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
//import org.bouncycastle.crypto.CipherParameters;
//import org.bouncycastle.crypto.engines.SM2Engine;
//import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
//import org.bouncycastle.crypto.params.*;
//import org.bouncycastle.jce.ECNamedCurveTable;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
//import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
//import org.bouncycastle.jce.spec.ECPrivateKeySpec;
//import org.bouncycastle.jce.spec.ECPublicKeySpec;
//import java.math.BigInteger;
//import java.security.*;
//import java.security.spec.ECGenParameterSpec;
//import java.util.Base64;
//import org.bouncycastle.crypto.params.ParametersWithRandom;
//
//@Slf4j
//public class SM2Util {
//
//    private static final String KEY_ALGORITHM = "SM2";
//
//    private static final int KEY_SIZE = 256;
//
//    static {
//        // 在使用之前添加BouncyCastleProvider提供者
//        Security.addProvider(new BouncyCastleProvider());
//    }
//
//    // 生成密钥对
//    public static KeyPair generateKeyPair() throws Exception{
//        ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
//        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM, "BC");
//        keyPairGenerator.initialize(sm2Spec, new SecureRandom());
//        return keyPairGenerator.generateKeyPair();
//    }
//
//    // 获取公钥字符串
//    public static String getPublicKeyStr(KeyPair keyPair) {
//        PublicKey publicKey = keyPair.getPublic();
//        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
//    }
//
//    // 获取私钥字符串
//    public static String getPrivateKeyStr(KeyPair keyPair) {
//        PrivateKey privateKey = keyPair.getPrivate();
//        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
//    }
//
//    // 加密
//    public static String encrypt(String plainText, String publicKeyString) throws Exception {
//        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
//        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(ECNamedCurveTable.getParameterSpec("sm2p256v1").getCurve().decodePoint(publicKeyBytes), ECNamedCurveTable.getParameterSpec("sm2p256v1"));
//        PublicKey publicKey = KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(ecPublicKeySpec);
//
//        SM2Engine engine = new SM2Engine();
//        engine.init(true, new ParametersWithRandom((CipherParameters) publicKey, new SecureRandom()));
//
//        byte[] plainTextBytes = plainText.getBytes("UTF-8");
//        byte[] cipherBytes = engine.processBlock(plainTextBytes, 0, plainTextBytes.length);
//
//        return Base64.getEncoder().encodeToString(cipherBytes);
//    }
//
//    // 解密
//    public static String decrypt(String cipherText, String privateKeyString) throws Exception {
//        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
//        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(1, privateKeyBytes), ECNamedCurveTable.getParameterSpec("sm2p256v1"));
//        PrivateKey privateKey = KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(ecPrivateKeySpec);
//
//        SM2Engine engine = new SM2Engine();
//        engine.init(false, (CipherParameters) privateKey);
//
//        byte[] cipherBytes = Base64.getDecoder().decode(cipherText);
//        byte[] plainTextBytes = engine.processBlock(cipherBytes, 0, cipherBytes.length);
//
//        return new String(plainTextBytes, "UTF-8");
//    }
//
//    public static void main(String[] args) throws Exception {
//        KeyPair keyPair = generateKeyPair();
//        String publicKey = getPublicKeyStr(keyPair);
//        String privateKey = getPrivateKeyStr(keyPair);
//
//        System.out.println("公钥：" + publicKey);
//        System.out.println("私钥：" + privateKey);
//
//        String plainText = "春江潮水连海平，海上明月共潮生。滟滟随波千万里，何处春江无月明。";
//        String cipherText = encrypt(plainText, publicKey);
//        System.out.println("加密后的密文：" + cipherText);
//
//        String decryptedPlainText = decrypt(cipherText, privateKey);
//        System.out.println("解密后的明文：" + decryptedPlainText);
//    }
//}

//package com.atguigu.encryption.utils;
//import org.bouncycastle.asn1.gm.GMNamedCurves;
//import org.bouncycastle.asn1.x9.X9ECParameters;
//import org.bouncycastle.crypto.engines.SM2Engine;
//import org.bouncycastle.crypto.params.ECDomainParameters;
//import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
//import org.bouncycastle.crypto.params.ECPublicKeyParameters;
//import org.bouncycastle.crypto.params.ParametersWithRandom;
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
//import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
//import org.bouncycastle.jce.provider.BouncyCastleProvider;
//import org.bouncycastle.jce.spec.ECParameterSpec;
//import org.bouncycastle.jce.spec.ECPrivateKeySpec;
//import org.bouncycastle.jce.spec.ECPublicKeySpec;
//import org.bouncycastle.util.encoders.Hex;
//
//import java.math.BigInteger;
//import java.security.*;
//import java.security.spec.ECGenParameterSpec;
//
///**
// * @ClassName SM2Utils
// * @Description SM2算法工具类
// */
//public class SM2Util {
//    public static KeyPair createECKeyPair() {
//        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
//
//        // 获取一个椭圆曲线类型的密钥对生成器
//        final KeyPairGenerator kpg;
//        try {
//            kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
//            kpg.initialize(sm2Spec, new SecureRandom());
//
//            return kpg.generateKeyPair();
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//    }
//
//    public static String encrypt(String publicKeyHex, String data) {
//        return encrypt(getECPublicKeyByPublicKeyHex(publicKeyHex), data, 1);
//    }
//
//    public static String encrypt(BCECPublicKey publicKey, String data, int modeType) {
//        //加密模式
//        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
//        if (modeType != 1) {
//            mode = SM2Engine.Mode.C1C2C3;
//        }
//        ECParameterSpec ecParameterSpec = publicKey.getParameters();
//        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
//                ecParameterSpec.getG(), ecParameterSpec.getN());
//        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
//
//        SM2Engine sm2Engine = new SM2Engine(mode);
//
//        sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
//        byte[] arrayOfBytes = null;
//        try {
//            byte[] in = data.getBytes("utf-8");
//
//            arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
//        } catch (Exception e) {
//            System.out.println("SM2加密时出现异常:" + e.getMessage());
//            e.printStackTrace();
//        }
//        return Hex.toHexString(arrayOfBytes);
//    }
//
//    public static String decrypt(String privateKeyHex, String cipherData) {
//        return decrypt(getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), cipherData, 1);
//    }
//
//    public static String decrypt(BCECPrivateKey privateKey, String cipherData, int modeType) {
//        //解密模式
//        SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
//        if (modeType != 1)
//            mode = SM2Engine.Mode.C1C2C3;
//
//        byte[] cipherDataByte = Hex.decode(cipherData);
//        ECParameterSpec ecParameterSpec = privateKey.getParameters();
//        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
//                ecParameterSpec.getG(), ecParameterSpec.getN());
//        ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
//                ecDomainParameters);
//
//        SM2Engine sm2Engine = new SM2Engine(mode);
//        sm2Engine.init(false, ecPrivateKeyParameters);
//        String result = null;
//        try {
//            byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
//            result = new String(arrayOfBytes, "utf-8");
//        } catch (Exception e) {
//            System.out.println("SM2解密时出现异常" + e.getMessage());
//        }
//        return result;
//    }
//
//    private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
//
//    private static ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
//
//    public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
//
//        if (pubKeyHex.length() > 128) {
//            pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
//        }
//        String stringX = pubKeyHex.substring(0, 64);
//        String stringY = pubKeyHex.substring(stringX.length());
//        BigInteger x = new BigInteger(stringX, 16);
//        BigInteger y = new BigInteger(stringY, 16);
//
//        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
//
//        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
//    }
//
//    public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
//        BigInteger d = new BigInteger(privateKeyHex, 16);
//        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
//        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
//    }
//
//    public static void main(String[] args) {
//        String publicKeyHex = null;
//        String privateKeyHex = null;
//        KeyPair keyPair = createECKeyPair();
//        PublicKey publicKey = keyPair.getPublic();
//        if (publicKey instanceof BCECPublicKey) {
//            //获取65字节非压缩缩的十六进制公钥串(0x04)
//            publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
//            System.out.println("SM2公钥：" + publicKeyHex);
//        }
//        PrivateKey privateKey = keyPair.getPrivate();
//        if (privateKey instanceof BCECPrivateKey) {
//            //获取32字节十六进制私钥串
//            privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
//            System.out.println("SM2私钥：" + privateKeyHex);
//        }
//
//        /**
//         * 公钥加密
//         */
//        String data = "=========需要加密的数据=========";
//
//        //将十六进制公钥串转换为 BCECPublicKey 公钥对象
//        String encryptData = encrypt(publicKeyHex, data);
//        System.out.println("加密结果：" + encryptData);
//
//        /**
//         * 私钥解密
//         */
//        //将十六进制私钥串转换为 BCECPrivateKey 私钥对象
//        data = decrypt(privateKeyHex, encryptData);
//        System.out.println("解密结果：" + data);
//    }
//}


package com.atguigu.encryption.utils;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class SM2Util {

    public static final String KEY_ALGORITHM = "SM2";

    private static final String PUBLIC_KEY = "SM2PublicKey";

    private static final String PRIVATE_KEY = "SM2PrivateKey";


    // 生成密钥对
    public static Map<String, Object> initKey(Integer keysize) throws Exception {
        Security.addProvider(new BouncyCastleProvider()); // 添加 Bouncy Castle 作为提供者
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); // 指定使用 Bouncy Castle 的实现
        keyPairGen.initialize(keysize);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 获取公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    public static String getPublicKeyStr(Map<String, Object> keyMap) {
        PublicKey publicKey = (PublicKey) keyMap.get(PUBLIC_KEY);
        return encryptBASE64(publicKey.getEncoded());
    }

    public static String getPrivateKeyStr(Map<String, Object> keyMap) {
        PrivateKey privateKey = (PrivateKey) keyMap.get(PRIVATE_KEY);
        return encryptBASE64(privateKey.getEncoded());
    }

    public static PublicKey getPublicKey(String publicKeyString) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
        byte[] publicKeyByte = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 指定使用 Bouncy Castle 的实现

        return keyFactory.generatePublic(keySpec);
    }

    public static PrivateKey getPrivateKey(String privateKeyString) throws Exception {
        byte[] privateKeyByte = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 指定使用 Bouncy Castle 的实现

        return keyFactory.generatePrivate(keySpec);
    }

    public static String encryptBASE64(byte[] key) {
        return new String(Base64.getEncoder().encode(key));
    }

    public static byte[] decryptBASE64(String key) {
        return Base64.getDecoder().decode(key);
    }

    public static String encrypt(String text, String publicKeyStr) {
        try {
            Security.addProvider(new BouncyCastleProvider()); // 添加 Bouncy Castle 作为提供者
            log.info("明文字符串为:[{}]", text);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); // 指定使用 Bouncy Castle 的实现
            cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyStr));
            byte[] tempBytes = cipher.doFinal(text.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(tempBytes);
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + text + "]时遇到异常", e);
        }
    }

    public static String decrypt(String secretText, String privateKeyStr) {
        try {
            Security.addProvider(new BouncyCastleProvider()); // 添加 Bouncy Castle 作为提供者
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); // 指定使用 Bouncy Castle 的实现
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr));
            byte[] secretTextDecoded = Base64.getDecoder().decode(secretText.getBytes("UTF-8"));
            byte[] tempBytes = cipher.doFinal(secretTextDecoded);
            return new String(tempBytes);
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e);
        }
    }

    public static void main(String[] args) throws Exception {
        Map<String, Object> keyMap;
        String cipherText;
        String content = "春江潮水连海平，海上明月共潮生。滟滟随波千万里，何处春江无月明。";

        keyMap = initKey(256);
        String publicKey = getPublicKeyStr(keyMap);
        log.info("公钥:[{}]，长度:[{}]", publicKey, publicKey.length());
        String privateKey = getPrivateKeyStr(keyMap);
        log.info("私钥:[{}]，长度:[{}]", privateKey, privateKey.length());

        cipherText = encrypt(content, publicKey);
        log.info("加密后的密文:[{}]，长度:[{}]", cipherText, cipherText.length());

        String plainText = decrypt(cipherText, privateKey);
        log.info("解密后明文:[{}]", plainText);
    }
}
